mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-12 21:30:45 +01:00

Currently there's an implicit requirement that users of SimulatedNetwork should call it repeatedly, even if the return value of NextDeliveryTimeUs is unset. With this change, it will indicate that there might be a delivery in 5 ms at any time there are packets in queue. Which results in unchanged behavior compared to current usage but allows new users to expect robust behavior. Bug: webrtc:9510 Change-Id: I45b8b5f1f0d3d13a8ec9b163d4011c5f01a53069 Reviewed-on: https://webrtc-review.googlesource.com/c/120402 Commit-Queue: Sebastian Jansson <srte@webrtc.org> Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org> Cr-Commit-Position: refs/heads/master@{#26617}
273 lines
9.1 KiB
C++
273 lines
9.1 KiB
C++
/*
|
|
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include <utility>
|
|
|
|
#include "absl/memory/memory.h"
|
|
#include "call/degraded_call.h"
|
|
#include "rtc_base/location.h"
|
|
|
|
namespace webrtc {
|
|
|
|
namespace {
|
|
constexpr int64_t kDoNothingProcessIntervalMs = 5000;
|
|
} // namespace
|
|
|
|
FakeNetworkPipeModule::~FakeNetworkPipeModule() = default;
|
|
|
|
FakeNetworkPipeModule::FakeNetworkPipeModule(
|
|
Clock* clock,
|
|
std::unique_ptr<NetworkBehaviorInterface> network_behavior,
|
|
Transport* transport)
|
|
: pipe_(clock, std::move(network_behavior), transport) {}
|
|
|
|
void FakeNetworkPipeModule::SendRtp(const uint8_t* packet,
|
|
size_t length,
|
|
const PacketOptions& options) {
|
|
pipe_.SendRtp(packet, length, options);
|
|
MaybeResumeProcess();
|
|
}
|
|
|
|
void FakeNetworkPipeModule::SendRtcp(const uint8_t* packet, size_t length) {
|
|
pipe_.SendRtcp(packet, length);
|
|
MaybeResumeProcess();
|
|
}
|
|
|
|
void FakeNetworkPipeModule::MaybeResumeProcess() {
|
|
rtc::CritScope cs(&process_thread_lock_);
|
|
if (!pending_process_ && pipe_.TimeUntilNextProcess() && process_thread_) {
|
|
process_thread_->WakeUp(nullptr);
|
|
}
|
|
}
|
|
|
|
int64_t FakeNetworkPipeModule::TimeUntilNextProcess() {
|
|
auto delay = pipe_.TimeUntilNextProcess();
|
|
rtc::CritScope cs(&process_thread_lock_);
|
|
pending_process_ = delay.has_value();
|
|
return delay.value_or(kDoNothingProcessIntervalMs);
|
|
}
|
|
|
|
void FakeNetworkPipeModule::ProcessThreadAttached(
|
|
ProcessThread* process_thread) {
|
|
rtc::CritScope cs(&process_thread_lock_);
|
|
process_thread_ = process_thread;
|
|
}
|
|
|
|
void FakeNetworkPipeModule::Process() {
|
|
pipe_.Process();
|
|
}
|
|
|
|
DegradedCall::DegradedCall(
|
|
std::unique_ptr<Call> call,
|
|
absl::optional<BuiltInNetworkBehaviorConfig> send_config,
|
|
absl::optional<BuiltInNetworkBehaviorConfig> receive_config)
|
|
: clock_(Clock::GetRealTimeClock()),
|
|
call_(std::move(call)),
|
|
send_config_(send_config),
|
|
send_process_thread_(
|
|
send_config_ ? ProcessThread::Create("DegradedSendThread") : nullptr),
|
|
num_send_streams_(0),
|
|
receive_config_(receive_config) {
|
|
if (receive_config_) {
|
|
auto network = absl::make_unique<SimulatedNetwork>(*receive_config_);
|
|
receive_simulated_network_ = network.get();
|
|
receive_pipe_ =
|
|
absl::make_unique<webrtc::FakeNetworkPipe>(clock_, std::move(network));
|
|
receive_pipe_->SetReceiver(call_->Receiver());
|
|
}
|
|
if (send_process_thread_) {
|
|
send_process_thread_->Start();
|
|
}
|
|
}
|
|
|
|
DegradedCall::~DegradedCall() {
|
|
if (send_pipe_) {
|
|
send_process_thread_->DeRegisterModule(send_pipe_.get());
|
|
}
|
|
if (send_process_thread_) {
|
|
send_process_thread_->Stop();
|
|
}
|
|
}
|
|
|
|
AudioSendStream* DegradedCall::CreateAudioSendStream(
|
|
const AudioSendStream::Config& config) {
|
|
return call_->CreateAudioSendStream(config);
|
|
}
|
|
|
|
void DegradedCall::DestroyAudioSendStream(AudioSendStream* send_stream) {
|
|
call_->DestroyAudioSendStream(send_stream);
|
|
}
|
|
|
|
AudioReceiveStream* DegradedCall::CreateAudioReceiveStream(
|
|
const AudioReceiveStream::Config& config) {
|
|
return call_->CreateAudioReceiveStream(config);
|
|
}
|
|
|
|
void DegradedCall::DestroyAudioReceiveStream(
|
|
AudioReceiveStream* receive_stream) {
|
|
call_->DestroyAudioReceiveStream(receive_stream);
|
|
}
|
|
|
|
VideoSendStream* DegradedCall::CreateVideoSendStream(
|
|
VideoSendStream::Config config,
|
|
VideoEncoderConfig encoder_config) {
|
|
if (send_config_ && !send_pipe_) {
|
|
auto network = absl::make_unique<SimulatedNetwork>(*send_config_);
|
|
send_simulated_network_ = network.get();
|
|
send_pipe_ = absl::make_unique<FakeNetworkPipeModule>(
|
|
clock_, std::move(network), config.send_transport);
|
|
config.send_transport = this;
|
|
send_process_thread_->RegisterModule(send_pipe_.get(), RTC_FROM_HERE);
|
|
}
|
|
++num_send_streams_;
|
|
return call_->CreateVideoSendStream(std::move(config),
|
|
std::move(encoder_config));
|
|
}
|
|
|
|
VideoSendStream* DegradedCall::CreateVideoSendStream(
|
|
VideoSendStream::Config config,
|
|
VideoEncoderConfig encoder_config,
|
|
std::unique_ptr<FecController> fec_controller) {
|
|
if (send_config_ && !send_pipe_) {
|
|
auto network = absl::make_unique<SimulatedNetwork>(*send_config_);
|
|
send_simulated_network_ = network.get();
|
|
send_pipe_ = absl::make_unique<FakeNetworkPipeModule>(
|
|
clock_, std::move(network), config.send_transport);
|
|
config.send_transport = this;
|
|
send_process_thread_->RegisterModule(send_pipe_.get(), RTC_FROM_HERE);
|
|
}
|
|
++num_send_streams_;
|
|
return call_->CreateVideoSendStream(
|
|
std::move(config), std::move(encoder_config), std::move(fec_controller));
|
|
}
|
|
|
|
void DegradedCall::DestroyVideoSendStream(VideoSendStream* send_stream) {
|
|
call_->DestroyVideoSendStream(send_stream);
|
|
if (send_pipe_ && num_send_streams_ > 0) {
|
|
--num_send_streams_;
|
|
if (num_send_streams_ == 0) {
|
|
send_process_thread_->DeRegisterModule(send_pipe_.get());
|
|
send_pipe_.reset();
|
|
}
|
|
}
|
|
}
|
|
|
|
VideoReceiveStream* DegradedCall::CreateVideoReceiveStream(
|
|
VideoReceiveStream::Config configuration) {
|
|
return call_->CreateVideoReceiveStream(std::move(configuration));
|
|
}
|
|
|
|
void DegradedCall::DestroyVideoReceiveStream(
|
|
VideoReceiveStream* receive_stream) {
|
|
call_->DestroyVideoReceiveStream(receive_stream);
|
|
}
|
|
|
|
FlexfecReceiveStream* DegradedCall::CreateFlexfecReceiveStream(
|
|
const FlexfecReceiveStream::Config& config) {
|
|
return call_->CreateFlexfecReceiveStream(config);
|
|
}
|
|
|
|
void DegradedCall::DestroyFlexfecReceiveStream(
|
|
FlexfecReceiveStream* receive_stream) {
|
|
call_->DestroyFlexfecReceiveStream(receive_stream);
|
|
}
|
|
|
|
PacketReceiver* DegradedCall::Receiver() {
|
|
if (receive_config_) {
|
|
return this;
|
|
}
|
|
return call_->Receiver();
|
|
}
|
|
|
|
RtpTransportControllerSendInterface*
|
|
DegradedCall::GetTransportControllerSend() {
|
|
return call_->GetTransportControllerSend();
|
|
}
|
|
|
|
Call::Stats DegradedCall::GetStats() const {
|
|
return call_->GetStats();
|
|
}
|
|
|
|
void DegradedCall::SetBitrateAllocationStrategy(
|
|
std::unique_ptr<rtc::BitrateAllocationStrategy>
|
|
bitrate_allocation_strategy) {
|
|
call_->SetBitrateAllocationStrategy(std::move(bitrate_allocation_strategy));
|
|
}
|
|
|
|
void DegradedCall::SignalChannelNetworkState(MediaType media,
|
|
NetworkState state) {
|
|
call_->SignalChannelNetworkState(media, state);
|
|
}
|
|
|
|
void DegradedCall::OnAudioTransportOverheadChanged(
|
|
int transport_overhead_per_packet) {
|
|
call_->OnAudioTransportOverheadChanged(transport_overhead_per_packet);
|
|
}
|
|
|
|
void DegradedCall::OnSentPacket(const rtc::SentPacket& sent_packet) {
|
|
if (send_config_) {
|
|
// If we have a degraded send-transport, we have already notified call
|
|
// about the supposed network send time. Discard the actual network send
|
|
// time in order to properly fool the BWE.
|
|
return;
|
|
}
|
|
call_->OnSentPacket(sent_packet);
|
|
}
|
|
|
|
bool DegradedCall::SendRtp(const uint8_t* packet,
|
|
size_t length,
|
|
const PacketOptions& options) {
|
|
// A call here comes from the RTP stack (probably pacer). We intercept it and
|
|
// put it in the fake network pipe instead, but report to Call that is has
|
|
// been sent, so that the bandwidth estimator sees the delay we add.
|
|
send_pipe_->SendRtp(packet, length, options);
|
|
if (options.packet_id != -1) {
|
|
rtc::SentPacket sent_packet;
|
|
sent_packet.packet_id = options.packet_id;
|
|
sent_packet.send_time_ms = clock_->TimeInMilliseconds();
|
|
sent_packet.info.included_in_feedback = options.included_in_feedback;
|
|
sent_packet.info.included_in_allocation = options.included_in_allocation;
|
|
sent_packet.info.packet_size_bytes = length;
|
|
sent_packet.info.packet_type = rtc::PacketType::kData;
|
|
call_->OnSentPacket(sent_packet);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool DegradedCall::SendRtcp(const uint8_t* packet, size_t length) {
|
|
send_pipe_->SendRtcp(packet, length);
|
|
return true;
|
|
}
|
|
|
|
PacketReceiver::DeliveryStatus DegradedCall::DeliverPacket(
|
|
MediaType media_type,
|
|
rtc::CopyOnWriteBuffer packet,
|
|
int64_t packet_time_us) {
|
|
PacketReceiver::DeliveryStatus status = receive_pipe_->DeliverPacket(
|
|
media_type, std::move(packet), packet_time_us);
|
|
// This is not optimal, but there are many places where there are thread
|
|
// checks that fail if we're not using the worker thread call into this
|
|
// method. If we want to fix this we probably need a task queue to do handover
|
|
// of all overriden methods, which feels like overikill for the current use
|
|
// case.
|
|
// By just having this thread call out via the Process() method we work around
|
|
// that, with the tradeoff that a non-zero delay may become a little larger
|
|
// than anticipated at very low packet rates.
|
|
receive_pipe_->Process();
|
|
return status;
|
|
}
|
|
|
|
void DegradedCall::MediaTransportChange(
|
|
MediaTransportInterface* media_transport) {
|
|
// TODO(bugs.webrtc.org/9719) We should add support for media transport here
|
|
// at some point.
|
|
}
|
|
|
|
} // namespace webrtc
|